package org.frame.factory;

import org.frame.myaop.ChainManager;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class ObjectFactory implements IFactory{

    private Properties env ;

    private Map<String,Object> objs;

    public ObjectFactory(InputStream input) {
        this.loadInf(input);
        this.objs = new HashMap<>();
    }
    public void loadInf(InputStream input){
        if(env == null){
            env = new Properties();
        }


        try {
            this.env.load(input);
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//默认调用的都是单例模式
    public <T>T getObject(Class<T> clazz){
        Object ret = null;
        ret = this.getObject(clazz,true);

        return (T)ret;
    }

    @Override
    public Object getObject(String keyName) {
        Object ret = null;
        try {
            ret = this.getObject(keyName,true);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return ret;
    }

    private Object getObjectByClass(Class clazz){
        Object ret = null;
        try {
            ret = clazz.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ret;
    }

    private String getFullName(String keyName){
        return env.getProperty(keyName);
    }
    public Object getObject(String keyName,boolean isSingleton) throws ClassNotFoundException {
        Object ret = null;
        String fullName = this.getFullName(keyName);
        if(isSingleton){
            if(objs.containsKey(fullName)){
                ret = objs.get(fullName);
            }else{
                Class clazz = this.getObjectClass(fullName);
                ret = getObjectByClass(clazz);
                objs.put(fullName,ret);
            }
        }else{
            Class clazz = this.getObjectClass(fullName);
            ret = getObjectByClass(clazz);
        }

        return ret;
    }

    public Object getObject(Class clazz,boolean isSingleton){
        String fullName = clazz.getName();
        Object ret = null;
        if(isSingleton){
            if(objs.containsKey(fullName)){
                ret = objs.get(fullName);
            }else{
                ret = this.getObjectByClass(clazz);
                objs.put(fullName,ret);
            }
        }else{
            ret = getObjectByClass(clazz);
        }
        return ret;
    }

    public Object getProxyObject(String keyName,IAddFeature addFeature)  {
        Class clazz = this.getObject(keyName).getClass();//可以与配置文件通用
        Object ret = null;
        if(clazz == null){
            throw new RuntimeException("该类不存在，无法代理 !");
        }
        ret = ProxyFactory.getProxyObject(clazz,addFeature);
        return ret;
    }
    public Object getProxyObject(ChainManager cm){
        return ProxyFactory.getProxyObject(cm);
    }


    private Class getObjectClass(String className) throws ClassNotFoundException {
        Class clazz = null;

        clazz = Class.forName(className);

        return clazz;
    }
}
